<template>
    <div class="table-editor-box">
        <div class="table-editor-toolbar">
            <el-row :gutter="10">


                <el-col :span="1.5">
                    <el-tooltip effect="light" content="添加" placement="top-start">
                        <el-button icon="el-icon-plus" plain circle size="small" @click="inserFieldHandle" />
                    </el-tooltip>
                </el-col>

                <el-col :span="1.5">
                    <el-tooltip effect="light" content="删除" placement="top-start">
                        <el-button icon="el-icon-minus" plain circle size="small" @click="deleteFieldHandle" />
                    </el-tooltip>
                </el-col>


            </el-row>
        </div>
        <vxe-table :data="table.foreignKeys" :loading="tableLoading" size="mini" border stripe :keep-source="true" height="100%" ref="xTable"
            class="mytable-scrollbar" :column-config="{ resizable: true }" mouse-config="{area:true}"
            :row-config="{ isHover: true, isCurrent: true }" :keyboard-config="{ isClip: true, isDel: true }"
            :edit-config="{ trigger: 'click', mode: 'row', enabled: true }" :scroll-y="{ enabled: tru }"
            @cell-click="tableDesignCellHandle">
            <vxe-column type="seq" width="60"></vxe-column>
            <vxe-column field="name" title="名字" show-header-overflow="title" show-overflow="title" width="160"
                :edit-render="{ autofocus: '.vxe-input--inner' }">
                <template #edit="{ row }">
                    <vxe-input v-model="row.name" type="text" ></vxe-input>
                </template>
            </vxe-column>
            <vxe-column field="field" title="字段" show-header-overflow="title" show-overflow="title" width="160"
                :edit-render="{ autofocus: '.vxe-input--inner', events: { change: selectChange } }"><template
                    #edit="{ row }">
                    <vxe-select v-model="row.field" size="small" clearable multiple>
                            <vxe-option v-for="item in table.fields" :key="item.name" :value="item.name"
                                :label="item.name"></vxe-option>
                        </vxe-select>
                </template></vxe-column>
            <vxe-column field="refCatalog" title="被引用的数据库" show-header-overflow="title" show-overflow="title" width="160"
                :edit-render="{ autofocus: '.vxe-input--inner' }"><template #edit="{ row }">
                    <vxe-select v-model="row.refCatalog" filterable @change="getTables(row)" clearable
                    size="small" >
                        <vxe-option v-for="item in refCatalogs" :key="item.name" :value="item.name"
                            :label="item.name"></vxe-option>
                    </vxe-select>
                </template></vxe-column>
            <vxe-column field="refTable" title="被引用的表" show-header-overflow="title" show-overflow="title" width="160"
                :edit-render="{ autofocus: '.vxe-input--inner' }">           
                <template #edit="{ row }">
                    <vxe-select v-model="row.refTable" filterable @change="getTableCloumns(row)"
                    size="small"  >
                        <vxe-option v-for="item in refTables" :key="item.name" :value="item.name"
                            :label="item.name"></vxe-option>
                    </vxe-select>
                </template></vxe-column>
            <vxe-column field="refField" title="被引用的字段" show-header-overflow="title" show-overflow="title" width="160"
                :edit-render="{ autofocus: '.vxe-input--inner' }">
                <template #edit="{ row }">
                    <vxe-select v-model="row.refField" filterable  multiple
                    size="small" >
                        <vxe-option v-for="item in refFields" :key="item.name" :value="item.name"
                            :label="item.name"></vxe-option>
                    </vxe-select>
                </template></vxe-column>
                    <vxe-column field="byDelete" title="删除时" show-header-overflow="title" show-overflow="title" width="160"
                    :edit-render="{ autofocus: '.vxe-input--inner' }">
                   
                    <template #edit="{ row }">
                        <vxe-select v-model="row.byDelete"   
                        size="small" >
                        <vxe-option v-for="item in foreignKeyActionType" :key="item.name" :value="item.name"
                            :label="item.value"></vxe-option>
                    </vxe-select>
                    </template></vxe-column>
                        <vxe-column field="byUpdate" title="更新时" show-header-overflow="title" show-overflow="title" width="160"
                    :edit-render="{ autofocus: '.vxe-input--inner' }">
              
                    <template #edit="{ row }">
                        <vxe-select v-model="row.byUpdate"   
                        size="small" >
                        <vxe-option v-for="item in foreignKeyActionType" :key="item.name" :value="item.name"
                            :label="item.value"></vxe-option>
                    </vxe-select>
                    </template></vxe-column>
        
        </vxe-table>
        <div class="other-set-box">
            <el-form ref="rowOtherFormRef" :model="rowData" label-width="80px" size="small">
                <el-form-item :label="item.name" :prop="item.key" v-for="item in rowOtherFormConfigData.other">
                    <el-select v-model="rowData[item.key]" clearable filterable v-if="item.type === 'select'"
                        @change="updateRowEditState">
                        <el-option v-for="eo in item.data(rowData)" :key="eo.value" :label="eo.name" :value="eo.value" />
                    </el-select>
                    <el-checkbox v-model="rowData[item.key]" clearable v-if="item.type === 'checkbox'"
                        @change="updateRowEditState" />
                    <el-input v-model="rowData[item.key]" clearable v-if="item.type === 'input'" />
                    <el-input-number v-model="rowData[item.key]" controls-position="right" :min="0"
                        v-if="item.type === 'number'"></el-input-number>
                </el-form-item>
            </el-form>
        </div>

    </div>
</template>
<script setup>
import { ref, defineProps, nextTick, inject, toRefs, reactive, watch, computed, h, defineExpose } from "vue"
import { foreignKeyActionType } from "../../service/constant"
import {MetadataService} from "../../service/metadataService"
const props = defineProps({
    connId: {
        type: [String, Number],
        required: true,
        default: undefined
    },
    catalogName: {
        type: String,
        default: undefined
    },
    name: {
        type: String,
        default: undefined
    }
});
const $request = inject('$request');
const $message = inject('$message');
const $messageBox = inject('$messageBox');
const $bus = inject("$bus")
const $keymaster = inject("$keymaster");
const metadataService = new MetadataService($request,$message)
const copyCacheRow = ref("")
const table = reactive({
    catalogName: props.catalogName,
    name: props.name,
    fields: [],
    foreignKeys:[]
})

const xTable = ref(null);
const createState = ref(!props.tableName);
const tableLoading = ref(false)
const rowData = ref({});
const rowOtherFormConfigData = ref({});
const updateFieldData = ref([]);
const refCatalogs = ref([])
const refTables = ref([])
const refFields = ref([])

watch(
    rowData,
    (newValue, oldValue) => {
        if (newValue._X_ROW_KEY && oldValue._X_ROW_KEY && newValue._X_ROW_KEY === oldValue._X_ROW_KEY) {
            updateFieldData.value.push(newValue)
        }
    },
    { deep: true }
)

$bus.$on("filedsUpdateKey", (fileds) => {
    table.fields = fileds;
});

const inserFieldHandle = (item) => {
    const row = -1;

    let record = {
        checked: false,
        name: '', type: '', size: null, decimalDigits: null, nullable: true, primaryKey: false, comment: ''
    }
    if (item) {
        record = item;
    }
    table.fields.push(record)
    xTable.value.insertAt(record, row).then(({ row }) => {
        xTable.value.setEditRow(rowData)
    })
}

const deleteFieldHandle = () => {
    const row = xTable.value.getCurrentRecord();
    if (!row) {
        $message.warning("请选择一行数据");
        return
    }
    $messageBox.confirm(
        `确定要删除[${row.name}]?`,
        '消息', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
    }
    )
        .then(() => {
            xTable.value.removeCurrentRow()
            return true
        })
        .catch((e) => {
            return true;
        })
}






const getCatalogs = ()=>{
    metadataService.getCatalogs( props.connId)
    .then(res=>{
        refCatalogs.value = res;
    })
}

const getTables = (row)=>{
    refTables.value = [];
    row.refTable = "";
    metadataService.getTables( props.connId,row.refCatalog)
    .then(result=>{
        refTables.value = result;
    })
}

const getTableCloumns = (row) => {
    refFields.value = [];
    row.refField = "";
    metadataService.getTableColumns( props.connId,row.refCatalog,row.refTable)
    .then(result=>{
        refFields.value = result.rows;
    })
}

const rowCovert = (rows) => {
    const row = rows[0];
    let rowCover = {};
    rowCover.key = row.CONSTRAINT_NAME
    rowCover.name = row.CONSTRAINT_NAME;
    rowCover.field = rows.map(item=>item.COLUMN_NAME);
    rowCover.refCatalog = row.REFERENCED_TABLE_SCHEMA;
    rowCover.refTable = row.REFERENCED_TABLE_NAME;
    rowCover.refField = rows.map(item=>item.REFERENCED_COLUMN_NAME);
    rowCover.byDelete = row.DELETE_RULE;
    rowCover.byUpdate = row.UPDATE_RULE;
    return rowCover;

}







const getChangeData = () => {
    if (createState.value) {
        return xTable.value.getTableData().fullData;
    }
    let changeFieldData = xTable.value.getRecordset();
    for (const row of updateFieldData.value) {
        if (!changeFieldData.updateRecords.some(item => item._X_ROW_KEY === row._X_ROW_KEY)) {
            changeFieldData.updateRecords.push(row)
        }
    }
    return changeFieldData;
}

const selectChange = (row) => {
    this.$refs.xTable.clearActived()//清除单元格激活状态
    this.$refs.xTable.setActiveCell(row.row, row.column.property)//设置单元格为激活状态
}





const getForeignKeys = ()=>{
    xTable.value&& xTable.value.clearAll();
    tableLoading.value= true;
    metadataService.getTableForeignKeys(props.connId,table.catalogName, table.name)
    .then(result=>{
        table.foreignKeys = [];
                const groupedBy = {};
                for (const item of result.rows) {
                    if (groupedBy[item.CONSISTENT_NAME]) {
                        groupedBy[item.CONSISTENT_NAME].push(item);
                    } else {
                        groupedBy[item.CONSISTENT_NAME] = [item];
                    }
                }

                for (const row in groupedBy) {
                    table.foreignKeys.push(rowCovert(groupedBy[row]))
                }
                
    })
    .finally(()=>tableLoading.value = false)
}



const init = () => {
    nextTick(() => {
        $keymaster('ctrl+c', () => {

            const row = xTable.value.getCurrentRecord();
            if (!row) {
                return
            }
            copyCacheRow.value = JSON.parse(JSON.stringify(row));
            delete copyCacheRow.value._X_ROW_KEY;
            // xTableValue.clearCurrentRow();
            return true
        });
        $keymaster('ctrl+v', () => {
            if (copyCacheRow.value) {
                const row = xTable.value.getCurrentRecord();
                if (row == null || !xTable.value.isEditByRow(row)) {
                    inserFieldHandle(copyCacheRow.value);
                } else {
                    Object.assign(row, copyCacheRow.value)
                    xTable.value.setCurrentRow(row)
                }

            }
            return true
        });
    })
    getCatalogs();
    //如果表名已经传入，那么就不是新建表，需要从后台拉回表的元数据
    if (table.catalogName && table.name) {
        createState.value = false;

        getForeignKeys();
    }

}
init();
//重新刷新组件
const reload = () => {
    init();
}
//设置可访问参数和方法
defineExpose({ reload, getChangeData }) 
</script>

<style lang="scss" scoped>
.table-editor-box {
    height: 100%;
    display: flex;
    flex-direction: column;

    .table-editor-toolbar {
        padding: 0px 5px 5px 5px;
    }

    .other-set-box {
        height: 200px;
        background: #fff;
        border-top: 1px solid #cdcdcd;
        padding: 10px;
    }
}
</style>